#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/3/11 11:42
# @Author  : jeff
# @FileName: application_value
import os
from typing import Optional, Union, Any, List
import requests
import yaml

current_dir = os.path.dirname(os.path.abspath(__file__))
application_dir = os.path.abspath(os.path.join(current_dir, "../../"))

_IS_CLOUD: Union[bool] = False
_APPLICATION_NAME: Union[str] = None


def _cloud_ips() -> Union[List[str]]:
    global application_dir, _APPLICATION_NAME

    _APPLICATION_NAME = find_element(
        read_file(os.path.normpath(os.path.join(application_dir, 'cloud.yaml'))),
        'application.name'
    )
    return find_element(
        read_file(os.path.normpath(os.path.join(application_dir, 'cloud.yaml'))),
        'application.cloud.consul'
    )


def find_element(elem, value):
    # split path
    for i in value.split('.'):
        if isinstance(elem, dict):
            if "[" in i:
                key, index = i.split("[")
                index = int(index.replace("]", ""))
                elem = elem.get(key, [])[index]
            else:
                elem = elem.get(i, {})
        elif isinstance(elem, list):
            index = int(i.replace("[", "").replace("]", ""))
            elem = elem[index]
        else:
            elem = None
            break
    return elem


def check_file_exist() -> bool:
    global application_dir
    files = os.listdir(application_dir)
    for file in files:
        if os.path.isfile(os.path.join(application_dir, file)) and file == 'cloud.yaml':
            return True
    return False


def is_cloud_exist(func):
    def wrapper(*args, **kwargs):
        global _IS_CLOUD
        _IS_CLOUD = check_file_exist()
        result = func(*args, **kwargs)
        return result

    return wrapper


def read_file(_path, encoding: Optional[str] = None):
    with open(_path, "r", encoding='utf-8') as input_file:
        file_contents = input_file.read()
        return yaml.safe_load(file_contents)


def get_cloud_data() -> dict:
    global _APPLICATION_NAME
    ips = _cloud_ips()
    if _APPLICATION_NAME is None:
        raise ValueError('The application name cannot be empty')
    for ip in ips:
        url = f'http://{ip}/key/{_APPLICATION_NAME}'
        try:
            response = requests.get(url, timeout=4)
            response.raise_for_status()
            return response.json()[0]['Value']
        except requests.exceptions.RequestException:
            pass
    raise Exception('Unable to access any IP addresses.')


@is_cloud_exist
def _path(
        is_cloud: Optional[bool] = _IS_CLOUD,
        path: Optional[str] = None
) -> Union[str]:
    global application_dir
    if path is None:
        if is_cloud:
            return os.path.normpath(os.path.join(application_dir, 'cloud.yaml'))
        else:
            return os.path.normpath(os.path.join(application_dir, 'application.yaml'))
    else:
        if not os.path.exists(path):
            raise FileNotFoundError("Path '{}' does not exist".format(path))
        if not path.endswith('.yaml'):
            raise Exception("Path '{}' Not a yaml file".format(path))
        else:
            return path


def _read_yaml(
        _path=_path()
) -> Union[dict]:
    global _IS_CLOUD
    if _IS_CLOUD:
        return get_cloud_data()
    else:
        return read_file(_path, encoding='utf-8')


def application_value(
        data=_read_yaml(),
        value: Optional[str] = None
) -> Union[Any]:
    return find_element(elem=data, value=value)


if __name__ == '__main__':
    print(current_dir)
